package com.cskaoyan.javase.array._4operation._3curd;

import java.util.Arrays;
import java.util.Scanner;

/**
 * 数组是一个容器，可以用存放元素，存放数据。
 * 在实际开发中，工程中也会需要存放大量数据，这一般是通过数据库来实现的。实际开发的基本需求就是基于数据库的，对数据进行增删改查，即"crud"，也有很多中低级Java程序员自嘲自己为"crud工程师"。
 * 当然"crud"指的是：
 * c，creat：新增数据/增加。
 * r，retrieve：检索数据/查询。
 * u，update：更新数据/修改。
 * d，delete ：删除数据/删除。
 * 我们现在还没有学习过数据库，但是不重要。
 * 现在我们使用数组这个容器，来模拟数据库，实现日常开发中最常见的"crud"操作。
 *
 * 对数组容器就行增删改查
 *
 *  需求:
 *          现在有一个String数组容器,这个数组中存放姓名,并且姓名具有唯一性
 *          要求对该String容器实现crud;
 *
 * @since 10:50
 * @author wuguidong@cskaoyan.onaliyun.com
 */
public class Demo {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        String[] names = new String[10];
        names[0] = "吴亦凡";
        names[1] = "肖战";
        names[2] = "鹿晗";
        names[3] = "蔡徐坤";
        names[4] = "刘亦菲";
        printNames(names);
        System.out.println("-----------------------");
        System.out.println("请键盘录入一个要插入的姓名: ");
        String nameInsert = sc.nextLine();
        switch (createName(names, nameInsert)) {
            case 0:
                System.out.println("插入成功!");
                System.out.println("现在names数组为:");
                printNames(names);
                break;
            case 1:
                System.out.println("姓名重复,插入失败!");
                System.out.println("现在names数组为:");
                printNames(names);
                break;
            case 2:
                System.out.println("数组已满,插入失败!");
                System.out.println("现在names数组为:");
                printNames(names);
                break;
        }
        System.out.println("-----------------------");
        System.out.println("请输入您要删除的姓名: ");
        String nameDel = sc.nextLine();
        if (delName(names, nameDel)) {
            // 删除成功
            System.out.println("删除成功!");
            System.out.println("现在names数组为:");
            printNames(names);
        } else {
            System.out.println("删除失败!没有找到该元素!");
            System.out.println("现在names数组为:");
            printNames(names);
        }
        System.out.println("-----------------");
        System.out.println("请输入要修改的名字:");
        String nameUpdate = sc.nextLine();
        System.out.println("请输入修改后的名字:");
        String nameUpdateTarget = sc.nextLine();
        if (updateName(names, nameUpdate, nameUpdateTarget)) {
            System.out.println("修改成功!");
            System.out.println("现在names数组为:");
            printNames(names);
        } else {
            System.out.println("修改失败!没有找到该元素!");
            System.out.println("现在names数组为:");
            printNames(names);
        }

        System.out.println("---------------");
        System.out.println("请输入要查找的目标元素:");
        String nameRetrieve = sc.nextLine();
        if (getIndexByRetrieveName(names, nameRetrieve) == -1) {
            System.out.println("没有找到目标元素!");
        }else {
            System.out.println("找到了目标元素!");
        }


    }

    // 实现数组元素的打印,输出名字,去除掉数组中的null元素

    /**
     *  去除掉null元素,仅打印实际姓名
     * @param names 被打印的名字数组
     * @author wuguidong@cskaoyan.onaliyun.com
     * @since 2022/03/24 10:58
     */
    public static void printNames(String[] names) {
        // 去除掉数组中的null元素
        System.out.print("[");
        for (String name : names) {
            if (name == null) {
                // null元素要跳过不打印
                continue;
            }
            // 代码运行到这里,元素一定不是null
            System.out.print(name + ", ");
        }
        System.out.println("\b\b]");
    }

    // 增

    /**
     * 插入一个名字到String数组中,
     *  但是要求姓名具有唯一性
     *
     *  方法的返回值是一个int状态码:
     *      0: 表示插入成功
     *      1: 表示姓名重复,插入失败
     *      2: 表示数组已满,插入失败
     *
     * @param names 被新增的名字
     * @param target 被新增名字的数组
     * @return int
     * @author wuguidong@cskaoyan.onaliyun.com
     * @since 2022/03/24 11:01
     */
    public static int createName(String[] names, String target) {
        // 首先判断要插入名字的唯一性
        /*
            这里牵扯到如何判断两个String对象相等
            "=="是比较地址
            但是这里String对象不能比较地址
            比较字符串内容应该使用equals方法!
         */
        // 遍历names数组,查找是否存在name和target重复
        // 假设target是用户键盘录入的一个字符串,不可能为null
        for (String name : names) {
            if (target.equals(name)) {
                // 名字已经重复了,禁止插入
                return 1;
            }
        }
        // 代码运行到这里,name肯定是不重复的,可以插入
        // 这里插入名字,指的是找到一个null元素的位置,把name赋值进去,这里的插入实际上是赋值
        for (int i = 0; i < names.length; i++) {
            if (names[i] == null) {
                // 找到为null的位置,赋值
                names[i] = target;
                // 插入名字成功!
                return 0;
            }
        }
        // 如果遍历整个数组都没有插入成功,说明数组满了,没有null的位置了
        return 2;
    }

    // 删
    // 删除不是真正的删除,而是把name对象赋值为null

    /**
     *  true表示删除成功
     *  false表示删除失败,因为找不到这个元素
     * @param names 被删除的name
     * @param target 被删除元素的String数组
     * @return boolean
     * @author wuguidong@cskaoyan.onaliyun.com
     * @since 2022/03/24 11:25
     */
    public static boolean delName(String[] names, String target) {
        // 遍历查找target元素,删除
        for (int i = 0; i < names.length; i++) {
            if (target.equals(names[i])) {
                // 找到该元素,赋值为null 表示删除
                names[i] = null;
                return true;
            }
        }
        // 没找到这个元素,删除失败
        return false;
    }

    // 改,修改名字

    /**
     *  修改成功返回true
     *  修饰失败,因为没有找到目标元素,返回false
     * @param names 被修改name的String数组
     * @param target 被修改的名字
     * @param newName 修改后的名字取值
     * @return boolean
     * @author wuguidong@cskaoyan.onaliyun.com
     * @since 2022/03/24 11:37
     */
    public static boolean updateName(String[] names, String target, String newName) {
        // 要修改,需要先找到这个名字
        for (int i = 0; i < names.length; i++) {
            if (target.equals(names[i])) {
                // 找到修改的目标
                names[i] = newName;
                return true;
            }
        }
        // 没有找到目标元素,修改失败!
        return false;
    }

    // 查询
    // 查询指的是,通过查找目标元素,返回元素对应的下标

    /**
     *  如果能够正常查找到目标元素,那么返回下标
     *  如果方法返回-1,表示没找到该元素
     *
     * @param names 被查找元素的String数组
     * @param target 被查找的目标元素
     * @return int
     * @author wuguidong@cskaoyan.onaliyun.com
     * @since 2022/03/24 11:43
     */
    public static int getIndexByRetrieveName(String[] names, String target) {
        int targetIndex = -1;
        for (int i = 0; i < names.length; i++) {
            if (target.equals(names[i])) {
                targetIndex = i;
            }
        }
        return targetIndex;
    }
}
